// Exam.cpp: implementation of the CExam class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Exam.h"

#include <GL/gl.h>
#include <cmath>
#include <cassert>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

const double PI = 3.1415926535897932384626433832795;


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CExam::CExam()
: m_mapmode(0)
{
    m_lift = 0.0;
	m_move = 0.0;
	m_cokecan.LoadFile("cokecan.bmp");
	m_metal.LoadFile("canlid-texture.bmp");
	m_polishtop.LoadFile("244.bmp");
	m_polishlabel.LoadFile("emerge-label.bmp");
	m_kodakbox.LoadFile("kodakbox.bmp");
	m_hanoi.LoadFile("hanoi.bmp");
}

CExam::~CExam()
{

}



void CExam::Draw()
{
    glDisable(GL_LIGHTING);
    glColor3d(1., 1., 1.);

    glBegin(GL_LINES);
        glVertex3d(0., 0., 0.);
        glVertex3d(6, 0., 0.);
        glVertex3d(0., 0., 0.);
        glVertex3d(0., 6, 0.);
        glVertex3d(0., 0., 0.);
        glVertex3d(0., 0., 6.);
    glEnd();

    //
    // This little bit of code demonstrates how to use the m_lift member
    // variable for simple animation.  Remove as you do the exam.
    //

    glColor3d(0., 1., 0.);
    glBegin(GL_LINES);
        glVertex3d(-0.5, m_lift, 0.);
        glVertex3d(0.5, m_lift, 0.);
    glEnd();


    // Enable lighting
    glEnable(GL_LIGHTING);

    //
    // Your solution code for drawing will go here
    //


}

//
// Name :        CExam::Hole()
// Description : Handy, dandy function to make a round hole in a rectangle.
//               This function will create a rectangle that is horizontal
//               sitting centered on (p_x, p_y, p_z) with a p_diameter
//               hole in it.  
//

void CExam::Hole(double p_x, double p_y, double p_z, double p_diameter)
{
    double radius = p_diameter / 2.;

    glPushMatrix();
    glTranslated(p_x, p_y, p_z);

    int N = 32;
    for(int r=0;  r<N/4;  r++)
    {
        double sr1 = radius * -sin(double(r) / double(N) * 2. * PI);
        double cr1 = radius * cos(double(r) / double(N) * 2. * PI);
        double sr2 = radius * -sin(double(r+1) / double(N) * 2. * PI);
        double cr2 = radius * cos(double(r+1) / double(N) * 2. * PI);

        glBegin(GL_TRIANGLES);
        glNormal3d(0, 1, 0);

        glVertex3d(radius, 0, -radius);
        glVertex3d(cr2, 0, sr2);
        glVertex3d(cr1, 0, sr1);

        glVertex3d(-radius, 0, -radius);
        glVertex3d(-cr1, 0, sr1);
        glVertex3d(-cr2, 0, sr2);

        glVertex3d(-radius, 0, radius);
        glVertex3d(-cr2, 0, -sr2);
        glVertex3d(-cr1, 0, -sr1);

        glVertex3d(radius, 0, radius);
        glVertex3d(cr1, 0, -sr1);
        glVertex3d(cr2, 0, -sr2);

        glEnd();

    }

    glPopMatrix();
}


void CExam::DrawSegment(double x1 , double y1 , double nx1 , double ny1 , 
						double x2 , double y2 , double nx2 , double ny2, 
						double t1, double t2, 	double zoom_x,double zoom_y,
						int m_mapmode)
{
	const int N = 32;
	double rs = 2*PI/N;
	double r1 = 0;
	double r2 = rs;

	double sin1 = sin(r1);
	double cos1 = cos(r1);
	double sin2, cos2; 
	for(int i=0; i<N; i++)
	{
		sin2 = sin(r2);
		cos2 = cos(r2);
		double p1[3] = {x1*cos1, y1, x1*-sin1};
		double n1[3] = {nx1*cos1, ny1, nx1*-sin1};
		double p2[3] = {x1*cos2, y1, x1*-sin2};
		double n2[3] = {nx1*cos2, ny1, nx1*-sin2};
		double p3[3] = {x2*cos2, y2, x2*-sin2};
		double n3[3] = {nx2*cos2, ny2, nx2*-sin2};
		double p4[3] = {x2*cos1, y2, x2*-sin1};
		double n4[3] = {nx2*cos1, ny2, nx2*-sin1};
		
		glBegin(GL_QUADS);
			glNormal3dv(n1);
			if(m_mapmode==1&&i>N/2)
			glTexCoord2d(zoom_x*double(i)/N, t1);
			else if(m_mapmode==2) glTexCoord2d(0.5+cos(2*i*PI/N)/2, 0.5+sin(2*i*PI/N)/2);
			else if(m_mapmode==1&&i<=N/2) glDisable(GL_TEXTURE_2D);//when the other half do not need to map, 
			//disable the GL_TEXTURE_2D, has problem, need ask TA or Prof! Because still mapped some color
			else if(m_mapmode==0) glTexCoord2d(zoom_x*double(i)/N, t1);
			glVertex3dv(p1);			
			glNormal3dv(n2);
			if(m_mapmode==1&&i>N/2)
			glTexCoord2d(zoom_x*double(i+1)/N, t1);
			else if(m_mapmode==2) glTexCoord2d(0.5+cos(2*(i+1)*PI/N)/2, 0.5+sin(2*(i+1)*PI/N)/2);
			else if(m_mapmode==1&&i<=N/2) glDisable(GL_TEXTURE_2D);
			else if(m_mapmode==0)glTexCoord2d(zoom_x*double(i+1)/N, t1);
			glVertex3dv(p2);
			glNormal3dv(n3);
			if(m_mapmode==1&&i>N/2)
			glTexCoord2d(zoom_x*double(i+1)/N, t2);
			else if(m_mapmode==2) glTexCoord2d(.5, .5);
			else if(m_mapmode==1&&i<=N/2) glDisable(GL_TEXTURE_2D);
			else if(m_mapmode==0) glTexCoord2d(zoom_x*double(i+1)/N, t2);
			glVertex3dv(p3);
			glNormal3dv(n4);
			if(m_mapmode==1&&i>N/2)
			glTexCoord2d(zoom_x*double(i)/N, t2);
			else if(m_mapmode==2) glTexCoord2d(.5, .5);
			else if(m_mapmode==1&&i<=N/2) glDisable(GL_TEXTURE_2D);
			else if(m_mapmode==0) glTexCoord2d(zoom_x*double(i)/N, t2);
			glVertex3dv(p4);
		glEnd();

		r1 += rs; 
		r2 += rs; 
		sin1 = sin2; 
		cos1 = cos2;
	}
}

void CExam::DrawSegmentNsides(double x1, double y1, double nx1, double ny1, 
                        double x2, double y2, double nx2, double ny2, int N,
                        double t1, double t2)
{
    // We'll do 32 segments
    double rs = PI*2 / N;    // 2 * PI / N
    double r1 = 0;          // The first angle
    double r2 = rs;         // The second angle

    double sin1 = sin(r1);
    double cos1 = cos(r1);
    double sin2, cos2;

    for(int i=0;  i<N;  i++, r1+=rs, r2+=rs, sin1=sin2, cos1=cos2)
    {
        // Compute the other angles
        sin2 = sin(r2);
        cos2 = cos(r2);

        // The four points and four normals we'll need
        double p1[3] = {x1 * cos1, y1, x1 * -sin1}; 
        double n1[3] = {nx1 * cos1, ny1, nx1 * -sin1}; 
        double p2[3] = {x1 * cos2, y1, x1 * -sin2}; 
        double n2[3] = {nx1 * cos2, ny1, nx1 * -sin2}; 
        double p3[3] = {x2 * cos2, y2, x2 * -sin2}; 
        double n3[3] = {nx2 * cos2, ny2, nx2 * -sin2}; 
        double p4[3] = {x2 * cos1, y2, x2 * -sin1}; 
        double n4[3] = {nx2 * cos1, ny2, nx2 * -sin1}; 

        glBegin(GL_QUADS);
            glNormal3dv(n1);
            glTexCoord2d(double(i) / N, t1);
            glVertex3dv(p1);
            glNormal3dv(n2);
            glTexCoord2d(double(i+1) / N, t1);
            glVertex3dv(p2);
            glNormal3dv(n3);
            glTexCoord2d(double(i+1) / N, t2);
            glVertex3dv(p3);
            glNormal3dv(n4);
            glTexCoord2d(double(i) / N, t2);
            glVertex3dv(p4);
        glEnd();
    }
}

void CExam::DrawSegmentNsidesHole(double x1, double y1, double nx1, double ny1, 
                        double x2, double y2, double nx2, double ny2, int N,
                        double t1, double t2,int m_mapmode)
{
    // We'll do 32 segments
    double rs = PI*2 / N;    // 2 * PI / N
    double r1 = 0;          // The first angle
    double r2 = rs;         // The second angle

    double sin1 = sin(r1);
    double cos1 = cos(r1);
    double sin2, cos2;

    for(int i=0;  i<N;  i++, r1+=rs, r2+=rs, sin1=sin2, cos1=cos2)
    {
        // Compute the other angles
        sin2 = sin(r2);
        cos2 = cos(r2);

        // The four points and four normals we'll need
        double p1[3] = {x1 * cos1, y1, x1 * -sin1}; 
        double n1[3] = {nx1 * cos1, ny1, nx1 * -sin1}; 
        double p2[3] = {x1 * cos2, y1, x1 * -sin2}; 
        double n2[3] = {nx1 * cos2, ny1, nx1 * -sin2}; 
        double p3[3] = {x2 * cos2, y2, x2 * -sin2}; 
        double n3[3] = {nx2 * cos2, ny2, nx2 * -sin2}; 
        double p4[3] = {x2 * cos1, y2, x2 * -sin1}; 
        double n4[3] = {nx2 * cos1, ny2, nx2 * -sin1}; 
		//made special two sides
        glBegin(GL_QUADS);
            glNormal3dv(n1);
			if(m_mapmode==0)
            glTexCoord2d(0.5+.9*cos(2*i*PI/N+2*PI/8)/2, 0.5+.9*sin(2*i*PI/N+2*PI/8)/2);
			else if(m_mapmode==1){
				//if(r1>-PI/4&&r1<PI/4)
			if(i==0||i==2)
					glTexCoord2d(0.25, 0);
			if(i==1||i==3)
				glTexCoord2d(1., .13);}
			glVertex3dv(p1);
            glNormal3dv(n2);
            if(m_mapmode==0)
			glTexCoord2d(0.5+.9*cos(2*(i+1)*PI/N+2*PI/8)/2, 0.5+.9*sin(2*(i+1)*PI/N+2*PI/8)/2);
			else if(m_mapmode==1){
				//if(r1>-PI/4&&r1<PI/4)
			if(i==0||i==2)
					glTexCoord2d(0.75, 0);
			if(i==1||i==3)
				glTexCoord2d(1., .87);}
            glVertex3dv(p2);
            glNormal3dv(n3);
            if(m_mapmode==0)
			glTexCoord2d(.5,.5);
			else if(m_mapmode==1){
				//if(r1>-PI/4&&r1<PI/4)
				if(i==0||i==2)
			glTexCoord2d(.75, .23);
				if(i==1||i==3)
					glTexCoord2d(.8, .87);}
			glVertex3dv(p3);
            glNormal3dv(n4);
            if(m_mapmode==0)
			glTexCoord2d(.5,.5);
			else if(m_mapmode==1){
				//if(r1>-PI/4&&r1<PI/4)
				if(i==0||i==2)
					glTexCoord2d(0.25, .23);
			if(i==1||i==3)
				glTexCoord2d(.8, .13);}
            glVertex3dv(p4);
        glEnd();
	}
}

void CExam::DrawCup(void)
{
    glColor3d(1., 1., 1.);
    glBegin(GL_LINES);
        glVertex3d(0., 0., 0.);
        glVertex3d(6, 0., 0.);
        glVertex3d(0., 0., 0.);
        glVertex3d(0., 6, 0.);
        glVertex3d(0., 0., 0.);
        glVertex3d(0., 0., 6.);
    glEnd();

	GLfloat white[] = {1.f,0.9f,0.5f, 1.};
	glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,white);
	DrawSegment(1.25, 0.25, 1., 0., 1.25, 1.25, 1., 0.,0.,0.666);
	DrawSegment(1.125, 1.75, -1., 0., 1.125,0.25, -1., 0.);
	DrawSegment(1.5, 1.75, 0., 1., 1.125,1.75,0., 1.);
	DrawSegment(0., 0., 0., -1.,1.125, 0., 0., -1.);
	DrawSegment(1., 0.125, 0., 1.,0., 0., 0., 1.);

	const int N = 8; 
	double r = PI/2./N;
	double sin1 = 0;
	double cos1 = 0;
	double r1 = 0; 
	double r2 = r;
	double sin2, cos2;
	for(int i=0; i<N; i++){
		sin2 = sin(r2);
		cos2 = cos(r2);
		DrawSegment(1.0+0.25*sin1,0.25-0.25*cos1,sin1,-cos1,1.0+0.25*sin2, 0.25-0.25*cos2,sin2,-cos2);
		DrawSegment(1.0+0.125*sin2,0.25-0.125*cos2,-sin1,cos1,1.0+0.125*sin1, 0.25-0.125*cos1,-sin2,cos2);
		sin1 = sin2;
		cos1 = cos2;
		r1 +=r;
		r2 +=r;
	}
	double list[9][4] = {
			{1.25, 1.25, 1.0, 0.},          // Vertex 1 x, y, normalx, normaly
			{1.257, 1.3125, 0.971555, -0.23682},            // 2
			{1.281,	1.375, 0.913121742,	-0.407686993},      // 3
			{1.313,	1.4375, 0.809620071,	-0.586954292},  // 4
			{1.375,	1.5, 0.709940842,	-0.704261316},      // 5
			{1.437,	1.5625, 0.77695496,	-0.629556185},      // 6
			{1.478,	1.625, 0.914874385,	-0.403738603},      // 7
			{1.494,	1.6875, 0.985044851,	-0.172298119},  // 8
			{1.5, 1.75, 1.0, 0.}};          // 9

		for(int j=0;  j<8;  j++)
		{
			DrawSegment(list[j][0], list[j][1],
				list[j][2], list[j][3],
				list[j+1][0], list[j+1][1],
				list[j+1][2], list[j+1][3],
				0.666+double(j)/8*0.333,
				0.666+double(j+1)/8*0.333);
		}		
}

void CExam::DrawCokecan(void)
{
    glBegin(GL_LINES);
        glVertex3d(0., 0., 0.);
        glVertex3d(6, 0., 0.);
        glVertex3d(0., 0., 0.);
        glVertex3d(0., 6, 0.);
        glVertex3d(0., 0., 0.);
        glVertex3d(0., 0., 6.);
    glEnd();	
	glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glBindTexture(GL_TEXTURE_2D,m_cokecan.TexName());
	DrawSegment(1.3,.25, 1.,0.,1.3, 4.15,1.,0.,0.,0.8); //Draw side faces
	DrawSegment(1.3,4.15,0.848,0.53,1.05,4.55,0.848,0.53,0.8,1.0); // Draw top curve
	glDisable(GL_TEXTURE_2D);


	GLfloat silver[] = {0.f,0.f,.8f,1.f};
	DrawSegment(0.,0.,0.,-1.,1.,0.,0.,-1.); //Draw bottom circle
	DrawSegment(1.05, 0.1,0.466,-0.28,1.3,0.25,0.466,-0.28); //Draw Secondary lowest large curve
	DrawSegment(1.,0., .446, -0.893, 1.05,0.1,.446, -0.893); //Draw lowest small curve
	DrawSegment(1.05, 4.55,1.,0., 1.05, 4.75, 1., 0);
	DrawSegment(1.0, 4.75,-1.,0., 1.00, 4.55, -1., 0);
	DrawSegment(1.05, 4.75, 0.,1., 1.0, 4.75, 0., 1.);
	glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glBindTexture(GL_TEXTURE_2D,m_metal.TexName());
	DrawSegment(1.,4.6,0.,1.,0.,4.6,0.,1.,0,1,1,1,2);
	glDisable(GL_TEXTURE_2D);
}

void CExam::DrawPolish(void)
{
	GLfloat white[] = {1.f,1.f,1.f, 1.};
	glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,white);
/*Draw bottle with curved bottom and texture*/
	glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glBindTexture(GL_TEXTURE_2D,m_polishlabel.TexName());
	DrawSegment(0.55,0.1,1.,0.,0.55,1.48, 1., 0.,0.,1.,2.,1,1); //external side faces
	glDisable(GL_TEXTURE_2D);
	GLfloat red[] = {.6f,.161f,.26f, 1.};
	glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,red);

	DrawSegment(0.4,1.48,-1.,0.,0.4,0.1, -1., 0.);//internal side faces
	DrawSegment(0.55,1.48, 0.707,0.707, 0.45,1.58,0.707,0.707);//'\' part
	DrawSegment(0.45,0., 0.707,-0.707, 0.55,0.1,0.707,-0.707);//'/' part
	DrawSegment(0.12,1.48,0.,-1.,0.45,1.48,0.,-1); //top inside
	DrawSegment(0.45,0.2, 1.,0., 0.,0.2,1.,0.);
	DrawSegment(0.45,1.58,1.,0.,0.32,1.58,1.,0.);//upper '-'
	DrawSegment(0.32,1.58,1.,0.,0.32,1.68,1.,0.);//'|'
	DrawSegment(0.32,1.68,0.,1.,0.22,1.68,0.,1.);//lower '-'
	DrawSegment(0.22,1.68,1.,0.,0.22,2.18,1.,0.); //top tube outer side
	DrawSegment(0.12,2.18,-1.,0.,0.12,1.68,-1.,0.); //top tube inner side
	DrawSegment(0.22,2.18,0.,1.,0.12,2.18,0.,1.);//topper '-'
	//Buttom curved surface, has problem!!!
		double list[6][4] = {
			{0., .05, 0., -1.},          // Vertex 1 x, y, normalx, normaly
			{.09,.04, -0.1104,-0.9939},            // 2
			{.18,.03, -0.2,-0.98},      // 3
			{.27,.02, -0.3,-0.97 },  // 4
			{.36,.01, -0.4,-0.96 },      // 5
			{.45, 0, -0.5,-0.96}};

		for(int j=0;  j<6;  j++)
		{
			DrawSegment(list[j][0], list[j][1],
				list[j][2], list[j][3],
				list[j+1][0], list[j+1][1],
				list[j+1][2], list[j+1][3]);
		}		
/*Draw white cap with texture*/
	glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,white);
	glPushMatrix();
	glTranslated(0.,1.68+m_lift,0.);

	DrawSegment(0.32,0.,1.,0.,0.27,1.75,1.,0.);//external side faces

	DrawSegment(0.20,1.68,-1,0.,0.25,0.,-1.,0.); //internal side faces
	glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glBindTexture(GL_TEXTURE_2D,m_polishtop.TexName());
	DrawSegment(0.27,1.75,0.,1.,0.,1.75,0.,1.,0,0,1,1,2);//top face
	glDisable(GL_TEXTURE_2D);
	DrawSegment(0.,1.68,0.,-1.,0.2,1.68,0.,-1.);//top face inside
	DrawSegment(0.25,0.,0.,-1.,0.32,0.,0.,-1);//side bottom lip
	glPopMatrix();
}

void CExam::DrawKodak(void)
{
    glBegin(GL_LINES);
        glVertex3d(0., 0., 0.);
        glVertex3d(6, 0., 0.);
        glVertex3d(0., 0., 0.);
        glVertex3d(0., 6, 0.);
        glVertex3d(0., 0., 0.);
        glVertex3d(0., 0., 6.);
    glEnd();	
	glRotated(45,0,1,0);
	/*bottom of the box*/
	DrawSegmentNsides(1.6,0.,1.,0.,1.60,.6,1.,0.,4); //external face sides
	DrawSegmentNsides(1.54,0.6,-1.,0.,1.54,0.,-1.,0.,4);//internal face sides
	DrawSegmentNsides(0.,0.,0.,-1.,1.60,0.,0.,-1.,4);//bottom side down
	DrawSegmentNsides(1.54,0.06,0.,1.,0.,0.06,0.,1.,4);//bottom side up
	DrawSegmentNsides(1.6,0.6,0.,1.,1.54,0.6,0.,1.,4); //lip side btw ext and int
	/*cap of the box*/
	glTranslated(0.,1.8+m_lift, 0.);	
	DrawSegmentNsides(1.54,0.6,-1.,0.,1.54,0.,-1.,0.,4);//internal face sides
	DrawSegmentNsides(0.,0.54,0.,-1.,1.54,0.54,0.,-1.,4);//top side down
	glEnable(GL_TEXTURE_2D);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glBindTexture(GL_TEXTURE_2D,m_kodakbox.TexName());
	DrawSegmentNsidesHole(1.6,0.,1.,0.,1.60,.6,1.,0.,4,0.,1.,1);//external face sides
	DrawSegmentNsidesHole(1.6,0.6,0.,1.,0.,0.6,0.,1.,4);//top side up
	glDisable(GL_TEXTURE_2D);
	DrawSegmentNsides(0.,0.54,0.,1.,1.54,0.54,0.,1.,4);
	
}

void CExam::DrawHanoi(void)
{
	GLfloat red[]={116./255., 56./255., 56./255.};
	GLfloat wood[]={228./255., 170./255., 114./255.};
	double r[8]={2.30/2., 1.975/2., 1.82/2.,1.65/2., 1.47/2., 1.29/2., 1.11/2., 0.95/2.};
	glPushMatrix();
	glTranslated(0.,0.5,0.);
	for(int i=0; i<8; i++){
		if(i==0||i==3||i==7){
			glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,red);
		}
		else glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,wood);
		if(i==7&&m_lift<=0.3){glTranslated(0,3*m_lift,0);}
		if(m_lift>0.3&&m_lift<0.6&&i==7)glTranslated(4.3*m_lift,0.9,0);
		if(m_lift>=0.6&&i==7)glTranslated(2.58,-2.3*m_move,0.);
		DrawSegment(r[i],0.,1.,0.,r[i],0.4,1.,0.);
		DrawSegment(0.075,0.4,-1,0.,0.075,0.,-1,0.);
		DrawSegment(r[i],0.4,0.,1.,0.075,0.4,0.,1);
		DrawSegment(0.075,0.,0.,-1.,r[i],0.,0.,-1);
		glTranslated(0.,0.4,0.);
	}
	glPopMatrix();
	for(int i=0; i<3; i++){
		glPushMatrix();
		glTranslated(2.58*(double)i,0.,0.);
		glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,wood);
		DrawSegment(0.07,0.5,1.,0.,0.07,3.85,1.,0.);
		DrawSegment(.07,3.85,0.,1.,0,3.85,0.,1);
		glPopMatrix();
	}
	/*
	   8---7
	  /   /
	 5---6
	  
	  3---4
	 /   /
	1---2
	*/
	double p1[3]={-3.875,0,1.325};
	double p2[3]={3.875,0,1.325};
	double p3[3]={-3.875,0,-1.325};
	double p4[3]={3.875,0,-1.325};
	double p5[3]={-3.875,0.5,1.325};
	double p6[3]={3.875,0.5,1.325};
	double p7[3]={3.875,0.5,-1.325};
	double p8[3]={-3.875,0.5,-1.325};
	glTranslated(2.58,0.,0.);
	glEnable(GL_TEXTURE_2D);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glBindTexture(GL_TEXTURE_2D,m_hanoi.TexName());
	glBegin(GL_QUADS);//top
		glNormal3d(0.,1.,0.);
		glTexCoord2d(.4,.12);glVertex3dv(p5);  glTexCoord2d(.4,.9);glVertex3dv(p6);
		glTexCoord2d(0,.9);glVertex3dv(p7); glTexCoord2d(0,0.12);glVertex3dv(p8); 
	glEnd();
	glDisable(GL_TEXTURE_2D);
	
	glBegin(GL_QUADS);//bottom
		glNormal3d(0.,-1.,0.);
		glVertex3dv(p1); glVertex3dv(p3); glVertex3dv(p4); glVertex3dv(p2);
	glEnd();
	
	glBegin(GL_QUADS);//front
		glNormal3d(0.,0.,1.);
		glVertex3dv(p1); glVertex3dv(p2); glVertex3dv(p6); glVertex3dv(p5);
	glEnd();
	
	glBegin(GL_QUADS);//back
		glNormal3d(0.,0.,-1.);
		glVertex3dv(p3); glVertex3dv(p8); glVertex3dv(p7); glVertex3dv(p4);
	glEnd();

	glBegin(GL_QUADS);//right
		glNormal3d(1.,0.,0.);
		glVertex3dv(p2); glVertex3dv(p4); glVertex3dv(p7); glVertex3dv(p6);
	glEnd();
	
	glBegin(GL_QUADS);//left
		glNormal3d(-1.,0.,0.);
		glVertex3dv(p3); glVertex3dv(p1); glVertex3dv(p5); glVertex3dv(p8);
	glEnd();
}

void CExam::DrawDuplo(void)
{
}

void CExam::DrawTest(double topedge_x,double topedge_y,double topofarc_y, double offset)
{
	//const int N=12;
	//double p1[3]={0,topedge_y,0};
	//double p2[3]={0,0,0};
	//double p3[3]={topedge_x,topofarc_y,0};
	//double p4[3]={topedge_x,topedge_y,0};
	//double delta_x=(p3[0]-p1[0]);
	//double delta_y=(p3[1]-p2[1]);
	//for(int i=0;i<N; i++){
	//	glBegin(GL_QUADS);
	//		glVertex3d(p1[0]+(double)delta_x*cos(PI*i/N),p1[1],0);
	//		glVertex3d(p1[0]+(double)delta_x*cos(PI*i/N),p2[1]+(double)delta_y*sin(PI*i/N)+.1,0);
	//		glVertex3d(p1[0]+(double)delta_x*cos(PI*(i+1)/N),p2[1]+(double)delta_y*sin(PI*(i+1)/N)+.1,0);
	//		glVertex3d(p1[0]+(double)delta_x*cos(PI*(i+1)/N),p1[1],0);
	//	glEnd();
	//}	
    glBegin(GL_LINES);
        glVertex3d(0., 0., 0.);
        glVertex3d(6, 0., 0.);
        glVertex3d(0., 0., 0.);
        glVertex3d(0., 6, 0.);
        glVertex3d(0., 0., 0.);
        glVertex3d(0., 0., 6.);
    glEnd();
	double pp5[3]={0,0,0};
	double pp6[3]={.75,.75,5.};
	double pp7[3]={0,1,2};
	double pp8[3]={1,2,5};
	double pp9[3]={2,2,6};
	double pp10[3]={0,2,4};
	glEnable(GL_TEXTURE_2D);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glBindTexture(GL_TEXTURE_2D,m_cokecan.TexName());
	glBegin(GL_TRIANGLES);
		double* n1 = SurfaceNormal(pp5,pp6,pp7);
		glNormal3dv(n1);
		glTexCoord2d(0,0);glVertex3dv(pp5);
		
		glTexCoord2d(3./8.,3./8.);glVertex3dv(pp6); 
		
		glTexCoord2d(0,.5);glVertex3dv(pp7);
		
	glEnd();

	glBegin(GL_TRIANGLES);
		double* n2 = SurfaceNormal(pp6,pp8,pp7);
		glNormal3dv(n2);
		glTexCoord2d(3./8.,3./8.);glVertex3dv(pp6);
		
		glTexCoord2d(3./8.,1);glVertex3dv(pp8);
	
		glTexCoord2d(0,.5);glVertex3dv(pp7);
		
	glEnd();

	glBegin(GL_TRIANGLES);
		double* n3 = SurfaceNormal(pp6,pp9,pp8);
		glNormal3dv(n3);
		glTexCoord2d(3./8.,3./8.);glVertex3dv(pp6); 
		glTexCoord2d(3./4.,1);glVertex3dv(pp9);
		glTexCoord2d(3./8.,1);glVertex3dv(pp8);
	glEnd();

	glBegin(GL_TRIANGLES);
		double* n4 = SurfaceNormal(pp7,pp8,pp10);
		glNormal3dv(n4);
		glTexCoord2d(0,.5);glVertex3dv(pp7);
		glTexCoord2d(3./8.,1);glVertex3dv(pp8);
		glTexCoord2d(0.,1);glVertex3dv(pp10);
		//glTexCoord2d(m_lift,m_lift);
	glEnd();
	
	double t1[2]={0.,1.};
	double t2[2]={3./8.,1};
	double t3[2]={0,.5};
	DrawQuad(pp10,pp8,pp7,NULL,t1,t2,t3);
	glDisable(GL_TEXTURE_2D);
}

double* CExam::SurfaceNormal(double* vt0, double* vt1, double* vt2)
{
	double v01[3];
	double v02[3];
	for(int i=0; i<3; i++){
		v01[i]=vt1[i]-vt0[i];
		v02[i]=vt2[i]-vt0[i];
	}
	double *cross = new double[3];
	cross[0]=v01[1]*v02[2]-v01[2]*v02[1];
	cross[1]=v01[2]*v02[0]-v01[0]*v02[2];
	cross[2]=v01[0]*v02[1]-v01[1]*v02[0];
	double norm=sqrt(pow(cross[0],2)+pow(cross[1],2)+pow(cross[2],2));
	for(int i=0; i<3; i++)
		cross[i]=cross[i]/norm;
	return cross;
}

void CExam::DrawQuad(double* v1, double* v2, double* v3, double* v4,double* t1, double* t2, double *t3, double* t4)
{
	if(v4!=NULL){
		glBegin(GL_QUADS);
			double* n = SurfaceNormal(v1,v2,v3);
			glNormal3dv(n);
			glTexCoord2dv(t1);glVertex3dv(v1);
			glTexCoord2dv(t2);glVertex3dv(v2);
			glTexCoord2dv(t3);glVertex3dv(v3);
			glTexCoord2dv(t4);glVertex3dv(v4);
		glEnd();
	}
	else {
		glBegin(GL_TRIANGLES);
			double* n = SurfaceNormal(v1,v2,v3);
			glNormal3dv(n);
			glTexCoord2dv(t1);glVertex3dv(v1);
			glTexCoord2dv(t2);glVertex3dv(v2);
			glTexCoord2dv(t3);glVertex3dv(v3);
		glEnd();
	}
}
